using System;
using System.Reflection;
using UniRx;
using VContainer;
using VContainer.Unity;
using TFramework.UI;
using TFramework.Events;
using TFramework.Extensions.VContainer;
using TFramework.IEnumeratorTool;
using TFramework;
using TFramework.ECS.Component.Manager;
using TFramework.ECS.Collection;
using TFramework.Pool;
using TFramework.ECS.Component;
using TFramework.ECS.Entity.Manager;
using TFramework.ECS.Group.Observable;
using TFramework.ECS.System.Manager;
using TFramework.ECS.System.Handler;

public class GameLanucher : LifetimeScope
{
    protected override void Awake()
    {
        base.Awake();
        gameObject.AddComponent<IEnumeratorTool>();
    }

    protected override void Configure(IContainerBuilder builder)
    {
        if (null == VContainerManager.Instance.LifetimeScope)
            VContainerManager.Instance.LifetimeScope = this;
        VContainerManager.Instance.Builder = builder;

        builder.Register<IMessageBroker, MessageBroker>(Lifetime.Singleton);
        builder.Register<IEventSystem, EventSystem>(Lifetime.Singleton);

        var componentTypeAssigner = new ComponentTypeAssigner();
        var allComponents = componentTypeAssigner.GenerateComponentLookups();
        var componentTypeLookup = new ComponentTypeLookup(allComponents);
        VContainerManager.Instance.Builder.RegisterInstance(componentTypeLookup).As<IComponentTypeLookup>();

        var componentDatabase = new ComponentDatabase(componentTypeLookup);
        VContainerManager.Instance.Builder.RegisterInstance(componentDatabase).As<IComponentDatabase>();

        builder.Register<IIdPool, IdPool>(Lifetime.Singleton);
        builder.Register<IEntityFactory, EntityFactory>(Lifetime.Singleton);
        builder.Register<IObservableGroupFactory, DefaultObservableObservableGroupFactory>(Lifetime.Singleton);
        builder.Register<IEntityCollection, EntityCollection>(Lifetime.Singleton);
        builder.Register<SetupSystemHandler>(Lifetime.Singleton);
        builder.Register<TeardownSystemHandler>(Lifetime.Singleton);
        builder.Register<UpdateSystemHandler>(Lifetime.Singleton);
        
        builder.RegisterEntryPoint<SystemLookup>(Lifetime.Singleton);

        builder.Register<UIManager>(Lifetime.Singleton);

        Assembly assembly = Assembly.Load("Game");
        InitAutoBindByInterface<IService>(assembly);
        InitAutoBindByInterface<IViewModelBase>(assembly);
        InitBindEntryPoint(assembly);
    }

    private void InitAutoBindByInterface<T>(Assembly dataAccess)
    {
        foreach (Type item in dataAccess.GetTypes())
        {
            var result = item.GetInterface(typeof(T).ToString());
            if (null == result)
                continue;
            VContainerManager.Instance.Builder.Register(item, Lifetime.Singleton);
        }
    }

    private void InitBindEntryPoint(Assembly dataAccess)
    {
        foreach (Type item in dataAccess.GetTypes())
        {
            var startable = item.GetInterface(typeof(IStartable).ToString());
            var tickable = item.GetInterface(typeof(ITickable).ToString());
            if (null != startable
            || null != tickable)
                VContainerManager.Instance.Builder.RegisterEntryPoint(item, Lifetime.Singleton);
        }
    }
}
